package BLEU;

@ISA = qw(Exporter);
@EXPORT = qw();

sub computeSmoothedBLEU {
	my $reference  = $_[0];
	my $candidate = $_[1];


	if($candidate eq "" && $reference eq "") {
		return 1;
	}
	elsif($candidate eq "" || $reference eq "") {
		return 0;
	}

	print STDERR "Candidate = $candidate, Reference = $reference\n";

	my(@CORRECT,@TOTAL,$length_translation,$length_reference);

    	chop;
        my @CWORD = split(/\s+/,$candidate);
        my %REF_NGRAM = ();
        my $length_translation_this_sentence = scalar(@CWORD);

        my ($closest_diff,$closest_length) = (9999,9999);

	my @RWORD = split(/ /,$reference);
	my $length = scalar(@RWORD);

	if (abs($length_translation_this_sentence-$length) < $closest_diff) {
	    $closest_diff = abs($length_translation_this_sentence-$length);
	    $closest_length = $length;
	}

	for(my $n=1;$n<=4;$n++) {
	    my %REF_NGRAM_N = ();
	    for(my $start=0;$start<=$#RWORD-($n-1);$start++) {
		my $ngram = "$n";
		for(my $w=0;$w<$n;$w++) {
		    $ngram .= " ".$RWORD[$start+$w];
		}
		$REF_NGRAM_N{$ngram}++;
	    }

	    foreach my $ngram (keys %REF_NGRAM_N) {
		if (!defined($REF_NGRAM{$ngram}) || 
		    $REF_NGRAM{$ngram} < $REF_NGRAM_N{$ngram}) {
		    $REF_NGRAM{$ngram} = $REF_NGRAM_N{$ngram};
		}
	    }
	}

    $length_translation += $length_translation_this_sentence;
    $length_reference += $closest_length;

    for(my $n=1;$n<=4;$n++) {
	my %T_NGRAM = ();
	for(my $start=0;$start<=$#CWORD-($n-1);$start++) {
	    my $ngram = "$n";
	    for(my $w=0;$w<$n;$w++) {
		$ngram .= " ".$CWORD[$start+$w];
	    }
	    $T_NGRAM{$ngram}++;
	}

	foreach my $ngram (keys %T_NGRAM) {
	    $ngram =~ /^(\d+) /;
	    my $n = $1;
#	print "$i e $ngram $T_NGRAM{$ngram}<BR>\n";
	    $TOTAL[$n] += $T_NGRAM{$ngram};
	    if (defined($REF_NGRAM{$ngram})) {
		if ($REF_NGRAM{$ngram} >= $T_NGRAM{$ngram}) {
		    $CORRECT[$n] += $T_NGRAM{$ngram};
#	    print "$i e correct1 $T_NGRAM{$ngram}<BR>\n";
		}
		else {
		    $CORRECT[$n] += $REF_NGRAM{$ngram};
#	    print "$i e correct2 $REF_NGRAM{$ngram}<BR>\n";
		}
	    }
	}
    }

     my $brevity_penalty = 1;
     if ($length_translation<$length_reference) {
              $brevity_penalty = exp(1-$length_reference/$length_translation);
     }

     my @bleu = ();
     $power = 0;
     my $NOR = 0;
     for($n=1;$n<=4;$n++) {
            $power+= my_log($CORRECT[$n]/$TOTAL[$n]) if($TOTAL[$n]);
	    $bleu[$n] = $brevity_penalty * exp($power/$n);
#            $NOR+=1/my_pow(2,4-$n+1) if($TOTAL[$n]);
     }

     my $sBLEU = 0;
     for($n=1;$n<=4;$n++) {
               $sBLEU += $bleu[$n]/my_pow(2,4-$n+1);
#		print STDERR "BLEU $n = $bleu[$n] sBLEU = $sBLEU\n";
     }

     print STDERR "sBLEU = $sBLEU\n";
     return $sBLEU;

}

sub my_log {
  return -9999999999 unless $_[0];
  return log($_[0]);
}

sub my_pow {
        my($b,$p) = ($_[0],$_[1]);
	return exp($p * log($b));
}

1;
